home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma1.arc / MSFILE.ASM < prev    next >
Assembly Source File  |  1986-02-13  |  40KB  |  1,570 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MSFILE -- Module to handle file I/O
  4.  
  5. ; Update 20 Jan 86
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13.     PUBLIC bufpnt, DTA, fcb, cpfcb, chrcnt, fixfcb, init, init1, gofil
  14.     PUBLIC outbuf, ptchr, gtchr, gtnfil, getfil, filbuf, encode, decode
  15.     PUBLIC nulref, nulr, decbuf, errpack, rptq, origr, rptct, rptval
  16.     PUBLIC clrfln, cxmsg, biterr, intmsg, Clear_percent_message
  17.     PUBLIC rppos, sppos, PerPr, KbPr, EOT_bells
  18.     PUBLIC kbpos, perpos, prtscr, Close_transfer_screen, AbFil
  19.     PUBLIC Say_aborted, Show_error, Show_warning, Show_status
  20.     PUBLIC Show_retries, Show_packets, Do_CXZ_mode_line
  21.     PUBLIC OFilSz, TFilSz, Write_to_standard_output
  22.  
  23.     INCLUDE MsDefs.H
  24.  
  25. rptmin    EQU 3            ; At least 3 of same char in a row
  26.  
  27. ; equates for screen positioning
  28. scrfln    EQU 0316H        ; Place for file name
  29. scrkb    EQU 0416H        ; Place for Kbytes transferred
  30. scrper    EQU 0516H        ; Place for percent transferred
  31. Start_of_percent_line EQU 0500h    ; Start of percent transferred line
  32. scrst    EQU 0616H        ; Place for status
  33. scrnp    EQU 0816H        ; Place for number of packets
  34. scrnrt  EQU 0916H        ; Place for number of retries
  35. screrr  EQU 0A16H        ; Place for error msgs
  36. ScrWrn    EQU 0B16H        ; Where warnings are displayed
  37. scrsp    EQU 0C00H        ; Place for send packet
  38. scrrp    EQU 0E00H        ; Place for receive packet
  39.  
  40. DataS    SEGMENT    PUBLIC 'DataS'
  41.  
  42.     extrn    data:byte, flags:byte, trans:byte, pack:byte, hierr:byte
  43.  
  44.     EVEN
  45.  
  46. temp1    DW ?            ; Temporary storage
  47. temp2    DW ?
  48. chrcnt  DW ?            ; Number of chars in the file buffer
  49. outpnt  DW ?            ; Position in packet
  50. bufpnt  DW ?            ; Position in file buffer
  51. fdtpnt    DW ?            ; Pointer to within our file
  52. fcbptr  DW ?            ; Position in FCB
  53. cbfptr  DW ?            ; Position in character buffer
  54. filsiz    DW 0            ; Double word for filesize (in bytes.)
  55.     DW 0
  56. ofilsz    DW 0            ; Original file size percent adjusted (/100)
  57. tfilsz    DW 0            ; Bytes transferred
  58.     DW 0
  59. oldper    DW 1234            ; old percentage
  60. oldper2    DW 101            ; old percentage 2 (after computation)
  61. oldkbt    DW ?            ; old KB transferred
  62. bufhex    DW 80H
  63.  
  64. File_handle DW 0        ; Handle of file we are currently working with
  65. File_buffer_ptr DW 0        ; Pointer into file buffer
  66. File_buffer_count DW 0        ; Number of bytes stored in buffer
  67.  
  68. ; File_buffer DB 2048 DUP (?)    ; Big buffer for reading and writing files
  69.  
  70. DTA    DB 128 DUP (?)        ; Used in wild-card searches
  71.  
  72. Ender    DB Bell, Bell, '$'    ; For end-of-transmission, if enabled
  73.  
  74. outlin  DB cr,lf,cr,lf
  75.     db      cr,lf,'           File name:'
  76.     db      cr,lf,'  KBytes transferred: 0'
  77.     db      cr,lf
  78.     db      cr,lf
  79.     db      cr,lf
  80.     db      cr,lf,'   Number of packets: 0'
  81.     db      cr,lf,'   Number of retries: 0'
  82.     db      cr,lf,'          Last error: None'
  83.     db      cr,lf,'        Last warning: None'
  84.     db      '$'
  85.  
  86. NRD_Msg1 DB 'Please insert a formatted disk in the disk drive, or$'
  87. NRD_Msg2 DB 'type control-C to ABORT.  Press any key when ready.$'
  88.  
  89. WRP_Msg1 DB 'Please remove the write-protect tab from the diskette,$'
  90. WRP_Msg2 DB 'or type control-C to ABORT.  Press any key when ready.$'
  91.  
  92. NRD_Addr1 EQU (19*256)+5    ; Locations for messages
  93. NRD_Addr2 EQU (20*256)+5
  94.  
  95. Abort_msg DB 'Aborted with ^C$'
  96. ermes4  DB 'Unable to rename file$'
  97. ermes4a    DB 'Remote '
  98.     Program_name
  99.     DB ': Unable to rename file$'
  100. erms10  DB 'Remote '
  101.     Program_name
  102.     DB ': Unable to receive data$'
  103. erms11  DB 'Disk full$'
  104. erms11a    DB 'Remote '
  105.     Program_name
  106.     DB ': Disk full$'
  107. ErMs12    DB 'Unable to create file$'
  108. ErMs12a    DB 'Remote '
  109.     Program_name
  110.     DB ': Unable to create file$'
  111. erms17  DB 'Record length exceeds size of buffer$'
  112. infms5  DB 'Renaming file to $'
  113. InfMs7    DB 'File interrupt$'
  114. InfMs8    DB 'File group interrupt$'
  115. hibit    DB 'Non-ASCII character in file$'
  116. Q_mark    DB '? $'
  117. Percent_sign DB '% $'
  118. crlf    DB cr,lf,'$'
  119. printer    DB 0,'LPT1       '
  120. spchar2    DB 24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  121.     DB 7BH,7DH,5FH,5EH,7EH,60H
  122. spc2len    EQU $-spchar2
  123. Tmp    DB ' ','$'        ; One char string
  124. next    DB 0FFH            ; No next character just yet
  125. rptval    DB 0            ; Repeated character
  126. rptct    DB 1            ; Number of times it's repeated
  127. rptq    DB drpt            ; Repeat prefix
  128. origr    DB drpt            ; Original repeat prefix
  129. wrpmsg    DB ?            ; non-zero if we wrote percent message
  130. permsg    DB cr,' Percent transferred:$'
  131. cxzhlp    DB '  Ret=Retry  ^X=Cancel file  ^Z=Cancel group'
  132.     DB '  ^E=Protocol abort  ^C=Full abort$'
  133. asmsg    DB ' as '
  134. asmln    EQU $-asmsg
  135. filbuf  DB 60H DUP(?)        ; Character buffer
  136.  
  137. fcb    DB fcbsiz DUP(?)    ; Use as our FCB
  138. cpfcb    DB fcbsiz DUP(?)    ; Save FCB in case of "*".   [7]
  139. decbuf    DB dmasiz DUP(?)    ; For decoding incoming data
  140.  
  141. DataS    ENDS
  142.  
  143. Code    SEGMENT    PUBLIC
  144.  
  145.     EXTRN SPack:NEAR, CmBlnk:NEAR, Locate:NEAR, Nout:NEAR
  146.     EXTRN PutMod:NEAR, PosCur:NEAR, ClearL:NEAR, FCBcpy:NEAR
  147.     EXTRN ClrMod:NEAR, Beep:NEAR, Get_Error:NEAR
  148.  
  149.     ASSUME cs:Code, ds:DataS
  150.  
  151. ; Display status of a file transfer
  152.  
  153. Show_status PROC
  154.  
  155.     cmp Flags.RemFlg, 0    ; In remote mode?
  156.      jz SST_0        ;  No
  157.  
  158.     ret            ; Quit quietly
  159.  
  160. SST_0:    push dx            ; Save ptr to message
  161.     mov dx, ScrSt        ; Position for status messages
  162.     call PosCur        ; Go there
  163.     call ClearL        ; Clear out any existing message
  164.     pop dx            ; Get back message
  165.  
  166. ;    jmp Write_to_standard_output ; Use standard routine to do this
  167.  
  168. Show_status ENDP
  169.  
  170.  
  171. Write_to_standard_output PROC
  172.  
  173.     mov di, dx        ; Copy to di
  174.     cld            ; Forwards
  175.     mov ax, ds        ; Copy ds ...
  176.     mov es, ax        ;  ... to es
  177.     mov cx, 300        ; Scan lots of characters
  178.     mov al, '$'        ; Want to find dollar sign
  179.     repne scasb        ; Search for it
  180.  
  181.     mov bx, di        ; Find length of string
  182.     sub bx, dx        ; Subtract ptr to start
  183.  
  184.     mov di, dx        ; Copy to di again
  185.     mov cx, 300        ; Scan lots of characters
  186.     sub al, al        ; Look for a zero this time
  187.     repne scasb        ; Search for it
  188.  
  189.     mov cx, di        ; Copy ending ptr to cx
  190.     sub cx, dx        ; Subtract ptr to start
  191.     cmp cx, bx        ; Use whichever length is LESS
  192.      jl WSO_1        ;  Stick with cx (0 is closer than dollar sign)
  193.  
  194.     mov cx, bx        ; Use the other value (dollar sign is closer)
  195.  
  196. WSO_1:    dec cx            ; Drop by 1 for terminating value
  197.  
  198.     mov ah, WRITEF2        ; Code to write to a file handle
  199.     mov bx, 1        ; Standard output
  200.     int Dos
  201.  
  202.     ret
  203.  
  204. Write_to_standard_output ENDP
  205.  
  206.  
  207. ; Display number of retries
  208.  
  209. Show_retries PROC
  210.  
  211.     cmp Flags.RemFlg, 0    ; In remote mode?
  212.      jz SRE_0        ;  No
  213.  
  214.     ret            ; Quit quietly
  215.  
  216. SRE_0:    mov dx, ScrNRt        ; Position for number of retries
  217.     call PosCur        ; Go there
  218.     mov ax, Pack.NumRtr    ; Number of retries
  219.     call Nout        ; Write the number
  220.     jmp ClearL        ; Clear out rest of line
  221.  
  222. Show_retries ENDP
  223.  
  224.  
  225. ; Display number of packets
  226.  
  227. Show_packets PROC
  228.  
  229.     cmp Flags.RemFlg, 0    ; In remote mode?
  230.      jz SPA_0        ;  No
  231.  
  232.     ret            ; Quit quietly
  233.  
  234. SPA_0:    mov dx, ScrNP        ; Position for number of packets
  235.     call PosCur        ; Go there
  236.     mov ax, Pack.NumPkt    ; Number of packets
  237.     jmp Nout        ; Write the number
  238.  
  239. Show_packets ENDP
  240.  
  241.  
  242. ; Say that file transfer has been aborted
  243.  
  244. Say_aborted PROC
  245.  
  246.     mov dx, OFFSET Abort_msg ; The message
  247. ;    jmp Show_error        ; Use other routine to display it
  248.  
  249. Say_aborted ENDP
  250.  
  251. ; Display an error message on a file transfer screen
  252.  
  253. Show_error PROC
  254.  
  255.     call Beep        ; Make a noise first
  256.     cmp Flags.RemFlg, 0    ; Are we in remote mode?
  257.      je SHE_0        ;  No
  258.  
  259.     push dx            ; Save reg
  260.     mov dx, OFFSET Q_mark    ; "? "
  261.     call Write_to_standard_output ; Output in binary mode
  262.     pop dx
  263.     jmp SHORT SHW_1        ; Join common code
  264.  
  265. SHE_0:    push dx            ; Save ptr to message
  266.     mov dx, ScrErr        ; Position for error messages
  267.     call PosCur        ; Go there
  268.     call ClearL        ; Clear out any existing message
  269.     pop dx            ; Get back message
  270.  
  271.     jmp SHORT SHW_1        ; Use warning code, same thing
  272.  
  273. Show_warning:
  274.     cmp Flags.RemFlg, 0    ; Are we in remote mode?
  275.      je SHW_0        ;  No
  276.  
  277.     push dx            ; Save reg
  278.     mov dx, OFFSET Percent_sign ; "% "
  279.     call Write_to_standard_output ; Output in binary mode
  280.     pop dx
  281.     jmp SHORT SHW_1        ; Join common code
  282.  
  283. SHW_0:    push dx            ; Save ptr to message
  284.     mov dx, ScrWrn        ; Position for warning messages
  285.     call PosCur        ; Go there
  286.     call ClearL        ; Clear out any existing message
  287.     pop dx            ; Get back message
  288.  
  289. SHW_1:    call Write_to_standard_output ; Output in binary mode
  290.     cmp Flags.RemFlg, 0    ; Are we in remote mode?
  291.      je SHW_2        ;  No
  292.  
  293.     mov dx, OFFSET CrLf    ; Ptr to CrLf
  294.     call Write_to_standard_output ; Output in binary mode
  295.  
  296. SHW_2:    stc            ; Force carry on in case it matters to anyone
  297.     ret            ; Done here
  298.  
  299. Show_error ENDP
  300.  
  301.  
  302. ; Reassure user that we acknowledge his ^X/^Z
  303.  
  304. INTMSG    PROC    NEAR
  305.  
  306.     cmp flags.xflg, 0    ; Writing to screen?
  307.      je INT_1        ;  No, ok to show this warning
  308.  
  309.     ret            ; Do nothing
  310.  
  311. INT_1:    mov dx, OFFSET InfMs7    ; File interrupted?
  312.     cmp flags.cxzflg, 'X'
  313.      je INT_2        ;  Yes
  314.  
  315.     mov dx, OFFSET InfMs8    ; File group interrupted
  316. INT_2:    jmp Show_warning    ; Put it on screen
  317.  
  318. INTMSG    ENDP
  319.  
  320.  
  321. ; Print err message that found a non-standard-Ascii char in the file
  322.  
  323. BITERR    PROC    NEAR
  324.     push bx
  325.     mov dx, OFFSET hibit    ; Message about non-ASCII chars
  326.     call Show_warning    ; Display it
  327.     pop bx
  328.     ret
  329. BITERR    ENDP
  330.  
  331. ;  Clear out message about interrupted file
  332.  
  333. CXMSG    PROC    NEAR
  334.  
  335.     cmp flags.xflg,0    ; Writing to screen?
  336.      jne cxm0        ; Yes. Don't do anything
  337.  
  338.     mov dx, ScrWrn
  339.     call poscur
  340.     call clearl
  341.  
  342. cxm0:    ret
  343.  
  344. CXMSG    ENDP
  345.  
  346.  
  347. ;  Clear out the old filename on the screen
  348.  
  349. CLRFLN    PROC
  350.  
  351.     mov dx,scrfln
  352.     call poscur
  353.     jmp clearl        ; Clear to end of line. [19a]
  354.  
  355. CLRFLN    ENDP
  356.  
  357. ; some random screen positioning functions
  358. kbpos:    mov dx,scrkb        ; KBytes transferred
  359.     call poscur
  360.     jmp clearl
  361. perpos:    mov dx,scrper        ; Percent transferred
  362.     call poscur
  363.     jmp clearl
  364. sppos:    mov dx,scrsp        ; Send packet location
  365.     jmp poscur
  366. rppos:    mov dx,scrrp        ; Receive packet location
  367.     jmp poscur
  368.  
  369.  
  370. ;  Initialize buffers and clear line
  371.  
  372. INIT    PROC
  373.  
  374.     call Make_console_binary ; Set "console" into binary mode so
  375.                 ;  "^C" isn't a problem
  376.  
  377.     cmp Flags.RemFlg, 0    ; Remote mode?
  378.      jne Init1        ;  Yes, no printing
  379.  
  380.     call cmblnk
  381.     call locate
  382.     mov ah,prstr        ; Put statistics headers on the screen
  383.     mov dx,offset outlin
  384.     int dos
  385.  
  386.     call Do_CXZ_mode_line    ; Use common code to do this
  387.  
  388.     mov wrpmsg,0        ; haven't printed the messsage yet
  389. ;    jmp init1
  390.  
  391. Init1:    mov chrcnt, dmasiz    ; Number of chars left
  392.     mov bufpnt, OFFSET DTA    ; Addr for beginning
  393.     mov hierr, 0
  394.  
  395.     ret
  396.  
  397. INIT    ENDP
  398.  
  399.  
  400. Do_CXZ_mode_line PROC
  401.  
  402.     cmp Flags.RemFlg, 0    ; In remote mode?
  403.      jz DCM_0        ;  No
  404.  
  405.     ret            ; Quit quietly
  406.  
  407. DCM_0:    mov dx, OFFSET CXZHlp
  408.     jmp PutMod        ; Write mode line
  409.  
  410. Do_CXZ_mode_line ENDP
  411.  
  412.  
  413. ; Common routine to close out any file transfer screen --
  414. ;  erase the mode line and position the cursor in the lower
  415. ;  left corner of the screen
  416.  
  417. Close_transfer_screen PROC
  418.  
  419.     call Make_console_ASCII    ; Set console back to ASCII mode
  420.  
  421.     cmp Flags.RemFlg, 0    ; In remote mode?
  422.      jz CTS_0        ;  No
  423.  
  424.     ret            ; Quit quietly
  425.  
  426. CTS_0:    call ClrMod        ; Erase the mode line
  427.     mov dx, 1600h        ; Line above lower left corner
  428.     jmp PosCur        ; Go there
  429.  
  430. Close_transfer_screen ENDP
  431.  
  432.  
  433. ; Switch console into and out of binary mode
  434.  
  435. Make_console_binary PROC
  436.  
  437.     mov ax, 4400h        ; IOCTL function 0, get device info
  438.     mov bx, 1        ; Standard output
  439.     int Dos            ; Get current info
  440.  
  441.     or dl, 20h        ; Turn on the binary bit
  442.     sub dh, dh        ; Clear high half
  443.  
  444.     mov ax, 4401h        ; IOCTL function 1, set device info
  445.     int Dos            ; Set it up
  446.  
  447.     ret
  448.  
  449. Make_console_binary ENDP
  450.  
  451. Make_console_ASCII PROC
  452.  
  453.     mov ax, 4400h        ; IOCTL function 0, get device info
  454.     mov bx, 1        ; Standard output
  455.     int Dos            ; Get current info
  456.  
  457.     and dl, NOT 20h        ; Turn on the binary bit
  458.     sub dh, dh        ; Clear high half
  459.  
  460.     mov ax, 4401h        ; IOCTL function 1, set device info
  461.     int Dos            ; Set it up
  462.  
  463.     ret
  464.  
  465. Make_console_ASCII ENDP
  466.  
  467.  
  468. ;    Output the chars in a packet
  469.  
  470. ; Called with AX = size of the data, BX = address of source
  471.  
  472. FILEIO    PROC
  473.  
  474. ptchr:  mov cx,ax
  475.     lea ax,outbuf        ; Where to put data when buffer gets full
  476. ;    jmp decode
  477.  
  478. ; CX = Size of data, BX = Address of data, AX = Routine to call to
  479. ; dump data
  480.  
  481. decode: push si
  482.     push di
  483.     push es
  484.     push dx
  485.     push ax
  486.     mov ax,ds
  487.     mov es,ax
  488.     pop ax
  489.     mov si,bx        ; Source of data
  490.     mov bx,ax        ; Coroutine to call
  491.     mov di,bufpnt        ; Destination of data
  492.     mov dh,0        ; assume no quote char
  493.     cmp trans.ebquot,'N'    ; no quoting?
  494.     je decod1        ; yes, keep going
  495.     cmp trans.ebquot,'Y'    ; or not doing it?
  496.     je decod1        ; yes, keep going
  497.     mov dh,trans.ebquot    ; otherwise use quote char
  498.  
  499. decod1:    mov rptct,0        ; Reset
  500.     mov rptval,0        ; Ditto
  501.     dec cx
  502.     jge dcod11        ; More data
  503.     jmp decod6        ; Else, we're through
  504.  
  505. dcod11:    dec chrcnt        ; Decrement number of chars in dta
  506.     jns decod2        ; Continue if space left
  507.     push cx
  508.     push dx
  509.     push bx
  510.  
  511.     call bx            ; Output it if full
  512.      jmp SHORT decod5    ;  Error return if disk is full
  513.      nop
  514.  
  515.     pop bx
  516.     pop dx
  517.     pop cx
  518.     mov di,bufpnt
  519.  
  520. decod2:    cmp rptct,0        ; Doing a repeat?
  521.      je dcod20        ;  No, so go get a character
  522.  
  523.     mov ah,0
  524.     mov al,rptval        ; Get the character we're repeating
  525.     jmp decod4        ; And write it out to the file
  526.  
  527. dcod20:    lodsb            ; Pick up a char
  528.     cmp rptq,0        ; Doing repeat quoting?
  529.     je dcod21        ; Nope, skip this part
  530.     cmp al,rptq        ; Did we pick up the repeat quote char?
  531.     jne dcod21        ; No, continue processing it
  532.     lodsb            ; Get the size
  533.     dec cx            ; Modify buffer count
  534.     sub al,20H        ; Was made printable
  535.     mov rptct,al        ; Remember how many repetitions
  536.     lodsb            ; Get the char to repeat
  537.     dec cx            ; Modify buffer count
  538. dcod21:    mov ah,00H        ; Assume no 8-bit quote char. [21b start]
  539.     cmp al,dh        ; This the 8-bit quot char?
  540.     jne decod3
  541.     lodsb            ; Get the real character
  542.     dec cx            ; Decrement # chars in packet
  543.     mov ah,80H        ; Turn on 8-bit quot char flag. [21b end]
  544. decod3: cmp al,trans.squote    ; Is it the quote char? [21b] [21c]
  545.     jne decod4        ; If not proceed
  546.     lodsb            ; Get the quoted character
  547.     dec cx            ; Decrement # of chars in packet
  548.     or ah,al        ; save parity (combine with prefix)
  549.     and ah,80h        ; only parity
  550.     and al,7FH        ; Turn off the parity bit
  551.     cmp al,trans.squote    ; Is it the quote char? [21c]
  552.     je decod4        ; If so just go write it out
  553.     cmp al,dh        ; This the 8-bit quot char?
  554.     je  decod4        ; If so, just go write it out
  555.     cmp al,rptq        ; Is is the repeat quote character?
  556.     je decod4        ; If so, just write it out
  557.     add al,40H        ; Make it a control char again
  558.     and al,7FH        ; Modulo 128
  559. decod4: or al,ah        ; or in parity
  560.     stosb            ; store the character
  561.     dec rptct        ; Repeat counter
  562.     cmp rptct,0        ; Write out char again?
  563.     jg dcod41
  564.     jmp decod1        ; No, get next char
  565. dcod41:    mov rptval,al        ; Save the char
  566.     jmp dcod11        ; and loop to next char
  567. decod5:    pop bx
  568.     pop dx            ; dx is pushed twice (really)
  569.     pop cx
  570.     pop dx
  571.     pop es
  572.     pop di
  573.     pop si
  574.     ret
  575. decod6:    mov bufpnt,di
  576.     pop dx
  577.     pop es
  578.     pop di
  579.     pop si
  580.     jmp rskp        ; Return successfully if done
  581.  
  582.  
  583.  
  584.     ; output the buffer, reset bufpnt and chrcnt
  585.  
  586. outbuf: cmp flags.xflg,1    ; Writing to screen? [21c]
  587.      je outbf2        ; Yes, handle specially. [21c]
  588.  
  589.     push bx
  590.     mov ah,writef        ; The write code
  591.     mov dx,offset fcb
  592.     int dos            ; Write the record
  593.     pop bx
  594.  
  595.     cmp al,0        ; Successful
  596.     jz outbf1
  597.  
  598.     push ax            ; Remember the return code. [20d]
  599.     call abfil        ; Fix things up before aborting. [20d]
  600.     pop ax            ; Retrive return code. [20d]
  601.  
  602.     cmp al,01
  603.      je outbf0
  604.  
  605.     mov dx, OFFSET erms17    ; Record length exceeds dta
  606.     call Show_error
  607.  
  608.     mov bx, OFFSET erms10    ; Text of message to send
  609.     jmp errpack        ; Send an error packet, ret from there
  610.  
  611. outbf0:    mov dx, OFFSET erms11    ; Disk full error
  612.     call Show_error
  613.  
  614.     mov bx, OFFSET erms11a    ; Text of message to send
  615.     jmp errpack        ; Send an error packet
  616.  
  617. outbf1:    add tfilsz+2,80H    ; Say 128 more characters received
  618.     adc tfilsz,0
  619.     call kbpr        ; Print the kilobytes received
  620.     call perpr        ; Print the percent ('?' for now)
  621.  
  622. outb11:    mov bufpnt,offset DTA    ; Addr for beginning
  623.     mov chrcnt,dmasiz-1    ; Buffer size
  624.     jmp rskp
  625.  
  626. outbf2:    mov cx,dmasiz-1        ; Number of chars to write. [21c]
  627.     sub cx,chrcnt        ; minus # of unused in buffer
  628.     mov di,offset DTA    ; Where they are. [21c]
  629.     call prtscr        ; Output buffer to screen. [21c]
  630.     jmp outb11        ; Reset counter & pointer. [21c]
  631.  
  632. ;  Tidy up before aborting.    [20d]
  633. ABFIL    PROC
  634.     mov ah,closf        ; Close the file
  635.     mov dx,offset fcb
  636.     int dos
  637.     cmp flags.abfflg,1    ; Delete what got across or keep it?
  638.     jne abfil0        ; Nope, keep it
  639.     mov ah,delf        ; Delete it
  640.     mov dx,offset fcb
  641.     int dos
  642. abfil0:    ret
  643. ABFIL    ENDP
  644.  
  645. ; General routine for sending an error packet.  Register BX should
  646. ; point to the text of the message being sent in the packet. [20f]
  647.  
  648. ERRPACK    PROC
  649.     mov di,offset data    ; Where to put the message
  650.     mov al,0
  651. errp1:    mov ah,[bx]
  652.     cmp ah,'$'        ; At end of message?
  653.     je errp2
  654.     inc al            ; Remember number of chars in msg
  655.     mov [di],ah
  656.     inc bx
  657.     inc di
  658.     jmp errp1
  659. errp2:    mov ah,0
  660.     mov pack.argbk1,ax
  661.     mov ah,'E'        ; And send an error packet
  662.     call spack
  663.      ret            ; Return if succeed or fail
  664.     nop
  665.     nop
  666.     ret
  667. ERRPACK    ENDP
  668.  
  669.  
  670. ;    Get the chars from the file
  671.  
  672. gtchr:  cmp flags.filflg,0    ; Is there anything in the DMA?
  673.     jz gtchr0        ; Yup, proceed
  674.     mov ah,rptq
  675.     mov origr,ah        ; Save repeat prefix here
  676.     mov rptct,1        ; Number of times char is repeated
  677.     mov rptval,0        ; Value of repeated char
  678.     call inbuf
  679.      jmp gtchr1        ; No more chars, go return EOF
  680.      nop            ; Make three bytes long
  681. gtchr0:    lea bx,inbuf
  682.     jmp encode
  683. gtchr1:    mov ax,0ffffh
  684.     ret
  685.  
  686. ; encode - writes data portion of kermit packet into filbuf
  687. ; expects BX to contain the address of a routine to refill the buffer,
  688. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  689. ; the maximum size of the data packet, bufpnt to contain a pointer to
  690. ; the source of the characters
  691. ; Returns: AX/ the number of characters actually written to the buffer
  692.  
  693. encode:    mov cl,trans.maxdat    ; Maximum packet size. [21b]
  694.     mov ch,0
  695.     mov di,offset filbuf    ; Where to put the data
  696.     mov si,bufpnt        ; pointer into source buffer
  697.     mov dl,trans.rquote    ; send quote char
  698.     mov dh,0        ; assume no 8-bit quoting
  699.     cmp trans.ebquot,'N'    ; not doing 8-bit quoting
  700.     je encod1
  701.     cmp trans.ebquot,'Y'    ; or can but won't?
  702.     je encod1
  703.     mov dh,0ffh        ; remember we have to do it
  704. encod1: dec cx            ; Decrement output buffer counter
  705.     jge encod2        ; Go on if there is more than one left
  706.     sub di,offset filbuf
  707.     mov ax,di
  708.     mov bufpnt,si        ; update pointer into DMA
  709.     jmp rskp
  710. encod2: dec chrcnt        ; any data in buffer?
  711.     jge encod3        ; yes, skip over buffer refill
  712.     call bx            ; Get another buffer full
  713.      jmp encod8
  714.     mov si,bufpnt        ; update position in DMA
  715.     cmp chrcnt,0        ; no characters returned?
  716.     jne encod3        ; Got some, keep going
  717.     jmp encod8        ; none, assume eof
  718. encod3:    lodsb
  719.     cmp rptq,0        ; Are we doing repeat prefixing?
  720.     je encd3x        ; Nope, skip next part
  721.     cmp chrcnt,0        ; Are we on the last character?
  722.     jle encd31        ; Yes, so there's no next character
  723.     cmp rptct,94        ; Max number that we can put in a byte
  724.     je encd31        ; Then that's it
  725.     mov ah,[si]        ; Get the next character
  726.     cmp al,ah        ; Is current char == next char?
  727.     jne encd31
  728.     inc rptct        ; Number of times char appears
  729.     mov rptval,al        ; Remember the character
  730.     inc cx            ; Repeats don't take up so much buffer space
  731.     jmp encod1        ; Keep checking for more
  732. encd31:    cmp rptct,1        ; Were previous characters repeats?
  733.     je encd3x        ; No, so just add this char
  734.     cmp rptct,rptmin    ; Are we within bounds for repeat prefixing?
  735.     jge encd32        ; Yes, use repeat prefixing
  736.     mov al,rptct
  737.     mov ah,0
  738.     sub si,ax        ; Not enough characters to warrant it
  739.     mov rptval,0        ; Clear out this value
  740.     inc cx            ; Adjust output buffer pointer
  741.     mov al,rptq
  742.     mov origr,al        ; Save original repeat prefix
  743.     mov rptq,0        ; Pretend we're not doing the prefixing
  744.     mov al,rptct
  745.     mov ah,0
  746.     add chrcnt,ax        ; Adjust input buffer pointer
  747.     jmp encod1        ; Reprocess those characters
  748. encd32:    push ax            ; Do repeat prefixing - save data
  749.     mov al,rptq        ; Add repeat prefix char
  750.     stosb
  751.     dec cx            ; Account for it in buffer size
  752.     mov al,rptct        ; Get the repeat count
  753.     add al,20H        ; Make it printable
  754.     stosb            ; Add to buffer
  755.     dec cx
  756.     pop ax            ; Get back the actual character
  757.     mov rptct,1        ; Reset repeat count
  758.     mov rptval,0        ; And this
  759.  
  760.  
  761. %OUT >> About half way through source file
  762.  
  763.  
  764. encd3x:    cmp dh,0        ; are we doing 8-bit quoting?
  765.      je encod4        ; no, forget this
  766.  
  767.     test al,80h        ; parity on?
  768.      je encod4        ; no, don't bother with this
  769.  
  770.     and al,7fh        ; turn off parity
  771.     push ax            ; save original char for a bit
  772.     dec cx            ; decrement # of chars left
  773.     mov al,trans.ebquot    ; get quote char
  774.     stosb            ; save in buffer
  775.     pop ax            ; restore character
  776.  
  777. encod4:    mov ah,al        ; save character
  778.     and ah,80h        ; only parity
  779.     and al,7fh        ; turn off parity in character
  780.     cmp al,' '        ; Compare to a space
  781.     jl encod5        ; If less then its a control char
  782.     cmp al,del        ; Is the char a delete?
  783.     jz encod5        ; Go quote it
  784.     cmp al,dl        ; Is it the quote char?
  785.     je encod6        ; Yes - go add it. [21b start]
  786.     cmp dh,0        ; are we doing 8-bit quoting?
  787.     je encd41        ; no, don't translate it
  788.     cmp al,trans.ebquot    ; Is it the 8-bit quote char?
  789.     je encod6        ; Yes, just output with quote
  790. encd41:    cmp origr,0        ; Doing repeat prefixing?
  791.     je encod7        ; No, don't check for quote char
  792.     cmp al,origr        ; Is this the repeat quote character
  793.     je encod6        ; Yes, then quote it
  794.     jmp short encod7    ; else don't quote it
  795. encod5:    add al,40h        ; control char, uncontrollify
  796.     and al,7fh
  797.  
  798. encod6:    push ax            ; save the char
  799.     dec cx
  800.     mov al,dl
  801.     stosb
  802.     pop ax
  803. encod7:    or al,ah        ; put parity back
  804.     stosb
  805.     cmp rptct,1        ; One occurence of this char?
  806.     jne encd7x
  807.     mov al,origr
  808.     mov rptq,al        ; Restore repeat quote char
  809.     jmp encod1        ; Yes, so loop around for some more
  810. encd7x:    dec rptct        ; Add another entry of this char
  811.     jmp encod1        ; With quoting and all
  812.  
  813. encod8: sub di,offset filbuf
  814.     or di,di
  815.     je encod9        ; Nope
  816.     mov ax,di
  817.     jmp rskp
  818. encod9: mov ax,0FFFFH        ; Get a minus one
  819.     ret
  820.  
  821.  
  822. inbuf:  mov ah,flags.eoflag    ; Have we reached the end?
  823.     cmp ah,0
  824.     jz inbuf0
  825.     ret            ; Return if set
  826. inbuf0:    push si
  827.     push di
  828.     push dx
  829.     push bx
  830.     push cx
  831.     mov bx,offset DTA    ; Set the r/w buffer pointer
  832.     mov bufpnt,bx
  833.     mov ah,readf        ; Read a record
  834.     mov dx,offset fcb
  835.     int dos
  836.     mov cx,filsiz
  837.     cmp cx,0        ; Check for 128 chars or less left
  838.     jne inbuf1        ; Still have data left
  839.     mov ax,ds
  840.     mov es,ax
  841.     mov si,offset filsiz+2
  842.     mov di,offset bufhex
  843.     cmps filsiz+2,es:bufhex
  844.     ja inbuf1        ; More than 128 chars
  845.     mov flags.eoflag,0FFH    ; Set End-of-file
  846.     mov cx,filsiz+2
  847.     cmp flags.filflg,0    ; Ever used DMA? [25]
  848.     jnz inbf01
  849.     dec cx            ; Account for DEC in caller routine
  850. inbf01:    mov chrcnt,cx        ; Return proper number of chars
  851.     mov flags.filflg,0    ; Buffer not empty
  852.     pop cx
  853.     pop bx
  854.     pop dx
  855.     pop di
  856.     pop si
  857.     jmp rskp
  858. inbuf1:    sub filsiz+2,80H    ; Sent another 128 chars
  859.     sbb filsiz,0        ; Account for the doubleword
  860.     add tfilsz+2,80H    ; Book keeping for the same
  861.     adc tfilsz,0
  862.     push ax
  863.     call kbpr        ; Print the kilobytes sent
  864.     call perpr        ; Print the percent sent
  865.     pop ax
  866.     mov al,80H        ; Use as counter for number of chars read
  867.     pop cx
  868.     pop bx
  869.     pop dx
  870.     pop di
  871.     pop si
  872.     cmp flags.filflg,0    ; Ever used DMA?
  873.     jnz inbf21        ; Nope, then don't change count
  874.     dec al            ; Fix boundary error
  875. inbf21: mov ah,0        ; Zero the flag (buffer not empty)
  876.     mov chrcnt,ax        ; Number of chars read from file
  877.     mov flags.filflg,0    ; Buffer not empty
  878.     jmp rskp
  879.  
  880. nulref:    mov chrcnt,0        ; No data to return
  881.     jmp rskp
  882.  
  883. nulr:    ret
  884.  
  885. ; Print the number of Kilobytes transferred
  886.  
  887. kbpr:    cmp flags.remflg,0    ; remote mode?
  888.     jne kbpr1        ; yes, no printing
  889.     mov ax,tfilsz+2
  890.     and ax,not (1111111111B) ; exclude low-order ten bits
  891.     or ax,tfilsz        ; get size words
  892.     cmp ax,oldkbt        ; is it the same?
  893.     je kbpr1        ; yes, no printing
  894.     mov oldkbt,ax
  895.     mov ax,tfilsz+2        ; Get low order word
  896.     mov cl, 10        ; Set up CL for shift count
  897.     shr ax,cl        ; Divide by 1024
  898.     mov bx,tfilsz        ; Get high order word
  899.     mov cl, 6        ; Set up CL for shift count
  900.     shl bx,cl        ; Move over to OR into AX
  901.     or ax,bx
  902.     push ax
  903.     call kbpos        ; Postion the cursor
  904.     pop ax
  905.     call nout        ; Print the number of KBytes transferred
  906. kbpr1:    ret
  907.  
  908.  
  909. ; Print the percent transferred
  910.  
  911. PerPr:    cmp Flags.RemFlg, 0    ; Remote mode?
  912.      jne PPR_3        ;  Yes, no printing
  913.  
  914.     cmp OFilSz, 0        ; Don't divide by zero
  915.      je PPR_3        ;  If not proceed
  916.  
  917.     mov ax, tfilsz        ; Build silly hash value
  918.     or ax, tfilsz+2
  919.     cmp ax, oldper        ; Same as it was before?
  920.      je PPR_3        ;  Yes, don't bother printing
  921.  
  922.     mov oldper, ax        ; Remember for next time
  923.  
  924.     cmp wrpmsg, 0        ; Did we write the percentage message?
  925.      jne PPR_1        ;  Yes, skip this part
  926.  
  927.     call PerPos        ; position cursor
  928.     mov ah, PrStr
  929.     mov dx, OFFSET PerMsg
  930.     int Dos            ; Write out message
  931.     mov WrPMsg, 1        ; Init flag so we don't do it again
  932.  
  933. PPR_1:    mov dx, TFilSz        ; Get the high order word
  934.     mov ax, TFilSz+2    ; Get the low order word
  935.     div OFilSz        ; Div by percent adjusted original file size
  936.     cmp ax, 100        ; > 100% ?
  937.      jle PPR_2        ;  No, accept it
  938.  
  939.     mov ax, 100        ; Else just use 100
  940.  
  941. PPR_2:    cmp ax, OldPer2        ; Same percent as last time?
  942.      je PPR_3        ;  Yes, don't flash cursor over same data
  943.  
  944.     mov OldPer2, ax        ; Save for next time here
  945.  
  946.     push ax            ; Save reg
  947.     call PerPos        ; Position the cursor
  948.     pop ax
  949.     call Nout
  950.     mov ah, ConOut        ; Print a character
  951.     mov dl, '%'        ; Load a percent sign
  952.     int Dos
  953.  
  954. PPR_3:    ret
  955.  
  956.  
  957. Clear_percent_message:
  958.  
  959.     mov WrpMsg, 0        ; Forget this was ever here
  960.     cmp Flags.RemFlg, 0    ; In remote mode?
  961.      jne CPM_0        ;  Yes, skip this
  962.  
  963.     cmp Flags.XFlg, 0    ; Writing to screen?
  964.      jne CPM_0        ;  Yes, skip this
  965.  
  966.     mov dx, Start_of_percent_line ; Where to go
  967.     call PosCur        ; Go there
  968.     call ClearL        ; Wipe the line
  969.  
  970. CPM_0:    ret            ; Done here
  971.  
  972.  
  973. EOT_bells:
  974.     cmp Flags.BelFlg, 0    ; Bell desired?
  975.      je CEB_0        ;  No
  976.  
  977.     mov ah, PrStr        ; Code to type a string
  978.     mov dx, OFFSET Ender    ; ^G^G
  979.     int Dos            ; Type it
  980.  
  981. CEB_0:    ret            ; Done here
  982.  
  983.  
  984. getfil: mov ah,0FFH
  985.     mov flags.filflg,ah    ; Nothing in the DMA
  986.     sub ax, ax
  987.     mov flags.eoflag,ah    ; Not the end of file
  988.     mov bx,offset fcb+0CH
  989.     mov [bx],ax        ; Zero the current block number
  990.     mov bx,offset fcb+0EH
  991.     mov [bx],ax        ; Ditto for Lrecl
  992.     mov bx,offset fcb+20H
  993.     mov [bx],ah        ; Zero the current record (of block)
  994.     inc bx
  995.     mov [bx],ax        ; Same for record (of file)
  996.     mov bx,offset fcb+23H
  997.     mov [bx],ax
  998.     mov ah,openf        ; Open the file
  999.     mov dx,offset fcb
  1000.     int dos
  1001.     mov dx,word ptr fcb+18    ; get file size (hi order word)
  1002.     mov filsiz,dx
  1003.     mov ax,word ptr fcb+16    ; lo order word
  1004.     mov filsiz+2,ax
  1005.     mov bx, 100        ; Get a 100
  1006.     div bx            ; Divide by it to convert for percentage
  1007.     mov ofilsz,ax
  1008.     mov tfilsz,0        ; Set bytes sent to zero
  1009.     mov tfilsz+2,0
  1010.     mov oldkbt,-1
  1011.     mov oldper,-1
  1012.     cmp filsiz,0        ; Null file?
  1013.     jne getfl0        ; Nope
  1014.     cmp filsiz+2,0        ; Null file?
  1015.     jne getfl0        ; Nope
  1016.     mov flags.eoflag,0FFH    ; Set EOF
  1017. getfl0:    jmp rskp
  1018.  
  1019.  
  1020. gtnfil: cmp flags.cxzflg,'Z'    ; Did we have a ^Z? [20b]
  1021.     je gtn5            ; If yes, we're done sending files. [20b]
  1022.     cmp flags.wldflg,0    ; Was there a "*"?        [7 start]
  1023.     je gtn5            ; Nope
  1024.     mov bx,offset cpfcb    ; Get FCB from last check for file.
  1025.     mov di,offset fcb    ; Copy to FCB
  1026.     mov cl,37        ; Size of FCB
  1027.     call fcbcpy
  1028. gtn2:    mov ah,snext
  1029.     mov dx,offset fcb    ; More files?
  1030.     int dos
  1031.     cmp al,0FFH
  1032.     je gtn5
  1033.     mov bx,offset fcb
  1034.     mov di,offset cpfcb
  1035.     mov cl,37
  1036.     call fcbcpy        ; Copy from FCB
  1037.     mov di,offset fcb+1    ; Get name of next file to send
  1038.     mov bx,offset DTA+1
  1039.     mov cl,11
  1040.     call fcbcpy
  1041.     call getfil        ; Initialize
  1042.      jmp r
  1043.     jmp rskp
  1044. gtn5:    mov flags.wldflg,0    ; Reset wild card flag
  1045.     ret                        ;  [7 end]
  1046.  
  1047.  
  1048. ;    Get the file name (including host to micro translation)
  1049.  
  1050.     PUBLIC GoFlx, GoFil0, GoFil7, GoFil1
  1051.  
  1052. gofil:  cmp flags.xflg,1    ; Remote command? [21c]
  1053.     jne goflx        ; No.... [21c]
  1054.     jmp gofla        ; Yes so skip this stuff. [21c]
  1055. goflx:    cmp flags.nmoflg,1    ; Overriding name from other side? [21a]
  1056.     jne gofil0        ; No - get the filename. [21a]
  1057.  
  1058. ; Have to set up TEMP2 in case file must be renamed
  1059.  
  1060.     mov cx, 9        ; Start here
  1061.     cmp FCB + 8, ' '    ; Blank here?
  1062.      jne goflx_0        ;  No
  1063.  
  1064.     mov cx, 7
  1065.     cmp FCB + 7, ' '    ; Blank here?
  1066.      jne goflx_0        ;  No
  1067.  
  1068.     dec cx
  1069.     cmp FCB + 6, ' '    ; Blank here?
  1070.      jne goflx_0        ;  No
  1071.  
  1072.     dec cx
  1073.     cmp FCB + 5, ' '    ; Blank here?
  1074.      jne goflx_0        ;  No
  1075.  
  1076.     dec cx
  1077.     cmp FCB + 4, ' '    ; Blank here?
  1078.      jne goflx_0        ;  No
  1079.  
  1080.     dec cx
  1081.     cmp FCB + 3, ' '    ; Blank here?
  1082.      jne goflx_0        ;  No
  1083.  
  1084.     dec cx
  1085.     cmp FCB + 2, ' '    ; Blank here?
  1086.      jne goflx_0        ;  No
  1087.  
  1088. goflx_0:
  1089.     mov temp2, cx        ; Save for possible rename
  1090.     jmp gofil7        ; Ignore packet contents
  1091.  
  1092. gofil0:    mov bx,offset data    ; Get the address of the file name. [21a]
  1093.     mov fdtpnt,bx        ; Store the address
  1094.     mov bx,offset fcb+1    ; Address of the FCB
  1095.     mov fcbptr,bx        ; Save it
  1096.     sub ax, ax
  1097.     mov temp1,ax        ; Initialize the char count
  1098.     mov temp2,ax
  1099.     cmp flags.droflg,1    ; Default drive? [21a]
  1100.     je gofil1        ; No - don't blank out value in FCB. [21a]
  1101.     mov si,offset fcb
  1102.     mov [si],ah        ; Set the drive to default to current
  1103. gofil1: mov ch,' '        ; Moved the label. [21a]
  1104.     mov [bx],ch        ; Blank the FCB
  1105.     inc bx
  1106.     inc ah
  1107.     cmp ah,0BH        ; Twelve?
  1108.     jl gofil1
  1109. gofil2: mov bx,fdtpnt        ; Get the NAME field
  1110.     mov ah,[bx]
  1111.     inc bx
  1112.     mov fdtpnt,bx
  1113.     cmp ah,'.'        ; Separator?
  1114.     jne gofil3
  1115.     mov bx,offset fcb+9
  1116.     mov fcbptr,bx
  1117.     mov ax,temp1
  1118.     mov temp2,ax
  1119.     mov temp1,9
  1120.     jmp gofil6
  1121. gofil3: cmp ah,0        ; Trailing null?
  1122.     jz gofil7        ; Then we're done
  1123.     call verlet        ; Verify that the char is legal
  1124.     mov bx,fcbptr
  1125.     mov [bx],ah
  1126.     inc bx
  1127.     mov fcbptr,bx
  1128.     mov ax,temp1        ; Get the char count
  1129.     inc ax
  1130.     mov temp1,ax
  1131.     cmp ax,8H        ; Are we finished with this field?
  1132.     jl gofil2
  1133. gofil4: mov temp2,ax
  1134.     mov bx,fdtpnt
  1135.     mov ah,[bx]
  1136.     inc bx
  1137.     mov fdtpnt,bx
  1138.     cmp ah,0
  1139.     jz gofil7
  1140.     cmp ah,'.'        ; Is this the terminator?
  1141.     jne gofil4        ; Go until we find it
  1142. gofil6: mov bx,fdtpnt        ; Get the TYPE field
  1143.     mov ah,[bx]
  1144.     inc bx
  1145.     mov fdtpnt,bx
  1146.     cmp ah,0        ; Trailing null?
  1147.     jz gofil7        ; Then we're done
  1148.     call verlet        ; Verify that the char is legal
  1149.     mov bx,fcbptr
  1150.     mov [bx],ah
  1151.     inc bx
  1152.     mov fcbptr,bx
  1153.     inc temp1        ; Increment char count
  1154.     cmp temp1,0CH        ; Are we finished with this field?
  1155.     jl gofil6
  1156. gofil7:    cmp flags.remflg,0    ; remote mode?
  1157.     jne gofil7a        ; yes, don't print it
  1158.     call prtfn        ; Print the file name. [21a]
  1159. gofil7a:cmp flags.destflg,0    ; Writing to the printer?
  1160.     jne gf7y
  1161.     push es
  1162.     mov ax,ds
  1163.     mov es,ax        ; Set this up
  1164.     mov cx,11
  1165.     mov si,offset printer
  1166.     mov di,offset fcb
  1167.     repne movsb        ; Change name in FCB to be printer
  1168.     pop es
  1169.     jmp gofil9
  1170. gf7y:    mov ah,flags.flwflg    ; Is file warning on?
  1171.     cmp ah,0
  1172.     jnz gf7x
  1173.     jmp gofil9        ; If not, just proceed
  1174.  
  1175. gf7x:
  1176.  
  1177. gf7xa:    mov ah,openf        ; See if the file exists
  1178.     mov dx,offset fcb
  1179.     int dos
  1180.     cmp al,0FFH        ; Does it exist?
  1181.      jnz gf8x        ; File exists, have to rename the incoming one
  1182.  
  1183.     call Check_for_Not_Ready ; Had an error, check for Drive Not Ready
  1184.      jnc gf7xa        ;  Drive Not Ready, user wants to try again
  1185.  
  1186.     jmp gofil9        ; Go create the file
  1187.  
  1188. gf8x:    mov dx, OFFSET InfMs5    ; Renaming file to ...
  1189.     call Show_warning
  1190.  
  1191.     mov ax,temp2        ; Get the number of chars in the file name
  1192.     cmp ax,0
  1193.      jne gofil8
  1194.  
  1195.     mov ax,temp1
  1196.     mov temp2,ax
  1197.  
  1198. gofil8: mov ch,0
  1199.     mov cl,al
  1200.     mov al,0        ; Says if first field is full
  1201.     cmp cl,9H        ; Is the first field full?
  1202.     jne gofl81
  1203.     mov al,0FFH        ; Set a flag saying so
  1204.     dec cl
  1205. gofl81: mov bx,offset fcb    ; Get the FCB
  1206.     add bx,cx        ; Add in the character number
  1207.     mov ah,'&'
  1208.     mov [bx],ah        ; Replace the char with an ampersand
  1209.     push ax
  1210.     push bx
  1211.     mov ah,openf        ; See if the file exists
  1212.     mov dx,offset fcb
  1213.     int dos
  1214.     pop bx
  1215.     cmp al,0FFH        ; Does it exist?
  1216.     pop ax
  1217.     jz gofl89        ; If not create it
  1218.     cmp al,0        ; Get the flag
  1219.     jz gofl83
  1220.     dec cl            ; Decrement the number of chars
  1221.     cmp cl,0
  1222.     jz gofl88        ; If no more, die
  1223.     jmp gofl81
  1224. gofl83: inc cl            ; Increment the number of chars
  1225.     cmp cl,9H        ; Are we to the end?
  1226.     jl gofl81        ; If not try again ; else fail
  1227.  
  1228. gofl88:    mov dx, OFFSET ErMes4    ; Unable to rename file
  1229.     call Show_error
  1230.  
  1231.     mov bx, OFFSET ErMes4a    ; Unable to rename file
  1232.     jmp errpack        ; Send error packet before abort. [20f]
  1233.  
  1234. gofl89:    cmp Flags.RemFlg, 0    ; Remote mode?
  1235.      jne gofil9        ;  Yes, don't have to print file name
  1236.  
  1237. ; Type out the selected file name
  1238.  
  1239.     mov cx, 8        ; Maximum number of chars to type
  1240.     mov dx, OFFSET Fcb+1    ; Addr of the file name part
  1241.     call Type_without_trailing_blanks ; Type the first part
  1242.  
  1243.     mov Tmp, '.'        ; Load a period
  1244.     mov ah, PrStr        ; Code to type string
  1245.     mov dx, OFFSET Tmp    ; The "string"
  1246.     int Dos            ; Type the period
  1247.  
  1248.     mov cx, 3        ; Maximum number of chars to type
  1249.     mov dx, OFFSET Fcb+9    ; Addr of the file type part
  1250.     call Type_without_trailing_blanks ; Type the second part part
  1251.  
  1252. gofil9:    mov ah,delf        ; Delete the file if it exists
  1253.     mov dx,offset fcb
  1254.     int dos
  1255.  
  1256.     sub ax, ax
  1257.     mov si,offset fcb+0CH
  1258.     mov [si],ax        ; Zero current block
  1259.     mov si,offset fcb+0EH
  1260.     mov [si],ax        ; Same for Lrecl
  1261.     mov si,offset fcb+20H
  1262.     mov [si],ah        ; Zero the current record (within block)
  1263.     inc si
  1264.     mov [si],ax        ; Zero record (within file)
  1265.     mov si,offset fcb+23H
  1266.     mov [si],ax
  1267.     mov ofilsz,0        ; File size unknown
  1268.     mov tfilsz,0        ; Set bytes received to zero
  1269.     mov tfilsz+2,0
  1270.     mov oldkbt,-1
  1271.     mov oldper,-1
  1272.  
  1273.     mov ah,makef        ; Now create it
  1274.     mov dx,offset fcb
  1275.     int dos
  1276.  
  1277.     cmp al,0FFH        ; Is the disk full?
  1278.     je gf9x
  1279.     jmp rskp
  1280.  
  1281. gf9x:    call Check_for_Write_Protect ; We had an error, see if it was WP
  1282.      jc gf9x0        ;  Not that type, or ABORT
  1283.  
  1284.     jmp gf7x        ;  Write Protect, user wants to try again, go
  1285.                 ;  all the way back to the Drive Ready check
  1286.  
  1287. gf9x0:    mov dx, OFFSET ErMs12    ; Unable to create file
  1288.     call Show_error
  1289.  
  1290.     mov bx, OFFSET ErMs12a    ; Unable to create file
  1291.     jmp errpack        ; Send an error packet
  1292.  
  1293. gofla:  cmp pack.argbk1,0    ; Any data in "X" packet? [21c start]
  1294.      je gofla1        ;  Nothing to print
  1295.  
  1296.     mov ah,prstr
  1297.     mov dx,offset crlf
  1298.     int dos
  1299.     mov di,offset data    ; Where data is
  1300.     mov cx,pack.argbk1    ; How much data we have
  1301.     call prtscr        ; Print it on the screen
  1302.  
  1303. gofla1:    mov ah,prstr
  1304.     mov dx,offset crlf
  1305.     int dos
  1306.  
  1307.     jmp rskp        ; And done. [21c end]
  1308.  
  1309. FILEIO    ENDP
  1310.  
  1311.  
  1312. ; Routines to put friendly messages on the screen in special cases of
  1313. ;  understandable disk errors -- Drive Not Ready and Write Protect Error
  1314.  
  1315. Tmsg    MACRO Message
  1316.     mov dx, OFFSET Message
  1317.     mov ah, PrStr
  1318.     int Dos
  1319.     ENDM
  1320.  
  1321. GoMsg    MACRO Prefix,Number
  1322.     mov dx, NRD_Addr&Number
  1323.     call PosCur
  1324.     Tmsg Prefix&_Msg&Number
  1325.     ENDM
  1326.  
  1327.     PUBLIC Check_for_Not_Ready, Check_for_Write_Protect
  1328.  
  1329. Check_for_Not_Ready PROC
  1330.  
  1331.     call Get_Error        ; See what the error code was
  1332.     cmp ax, 2        ; Code for Drive Not Ready
  1333.      jne CCC_Abort        ;  Not what we got, give up
  1334.  
  1335.     GoMsg NRD,1
  1336.     GoMsg NRD,2
  1337.     jmp SHORT Check_common_code
  1338.  
  1339. Check_for_Not_Ready ENDP
  1340.  
  1341.  
  1342. Check_for_Write_Protect PROC
  1343.  
  1344.     call Get_Error        ; See what the error code was
  1345.     cmp ax, 0        ; Code for Write Protect error
  1346.      jne CCC_Abort        ;  Not what we got, give up
  1347.  
  1348.     GoMsg WRP,1
  1349.     GoMsg WRP,2
  1350.  
  1351. Check_common_code:
  1352.     call Beep        ; Go make a noise
  1353.  
  1354.     mov ah, ConInQ        ; Quiet console input
  1355.     int Dos            ; Wait until user hits a key
  1356.  
  1357.     call Erase_error_message ; Get rid of the message
  1358.  
  1359.     cmp al, 3        ; Control-C?
  1360.      je CCC_Abort        ;  Yes, don't accept the file
  1361.  
  1362.     clc            ; Clear carry for no error
  1363.     ret            ; Return ready for retry
  1364.  
  1365. CCC_Abort:
  1366.     stc            ; Set carry for error
  1367.     ret            ; Return error
  1368.  
  1369. Check_for_Write_Protect ENDP
  1370.  
  1371.  
  1372.     PUBLIC Erase_error_message
  1373.  
  1374. Erase_error_message PROC
  1375.  
  1376. Clear_it MACRO Address
  1377.     mov dx, Address        ;; Position
  1378.     call PosCur        ;; Go there
  1379.     call ClearL        ;; Clear out any existing message
  1380.     ENDM
  1381.  
  1382.     push ax            ; Save reg
  1383.     Clear_it NRD_Addr1    ; Clear each line
  1384.     Clear_it NRD_Addr2
  1385.     pop ax            ; Restore reg
  1386.  
  1387.     ret
  1388.  
  1389. Erase_error_message ENDP
  1390.  
  1391.  
  1392. ; Call with ...
  1393. ;    cx/ maximum number of chars to type
  1394. ;    dx/ OFFSET within ds: of string to type
  1395.  
  1396.     PUBLIC Type_without_trailing_blanks
  1397.  
  1398. Type_without_trailing_blanks PROC
  1399.  
  1400. LP_1:    mov bx, cx        ; Copy to bx
  1401.     add bx, dx        ; Add in OFFSET to string
  1402.     cmp BYTE PTR -1[bx], ' ' ; Is this a space?
  1403.      jne Got_one
  1404.  
  1405.     loop LP_1
  1406.  
  1407.     ret            ; Nothing but blanks, print nothing
  1408.  
  1409. Got_one:
  1410.     cld            ; Forwards
  1411.     mov ah, PrStr        ; Doing this repeatedly
  1412.     mov si, dx        ; Start at start of string
  1413.     mov dx, OFFSET Tmp    ; Point at Tmp string
  1414.  
  1415. LP_2:    lodsb            ; Pick up this byte
  1416.     mov Tmp, al        ; Copy to Tmp
  1417.     int Dos            ; Type the next byte
  1418.     loop LP_2        ; Go do another one
  1419.  
  1420.     ret            ; Done here
  1421.  
  1422. Type_without_trailing_blanks ENDP
  1423.  
  1424. ; Passed char of incoming filename in AH.  Verify that it is legal
  1425. ; and if not change it to an "X"
  1426. verlet:    cmp ah,'0'
  1427.     jl ver2            ; See if it's a legal weird char
  1428.     cmp ah,'z'+1
  1429.     jns ver2
  1430.     cmp ah,'9'
  1431.     jle ver1        ; It's between 0-9 so it's OK
  1432.     cmp ah,'A'
  1433.     jl ver2            ; Coud be a weird char
  1434.     cmp ah,'Z'
  1435.     jle ver1        ; It's A-Z so it's OK
  1436.     cmp ah,'a'
  1437.     jl ver2
  1438.     and ah,137O        ; It's a-z, capitalize
  1439. ver1:    ret
  1440.  
  1441. ver2:    push es
  1442.     mov cx,ds
  1443.     mov es,cx        ; Scan uses ES register
  1444.     mov di,offset spchar2
  1445.     mov cx,spc2len
  1446.     mov al,ah        ; Char is in al
  1447.     repnz scasb        ; Search string for input char
  1448.     pop es
  1449.     mov ah,al        ; Return it in AH
  1450.     cmp cx,0        ; Was it there?
  1451.     jnz ver1        ; Yes, return it
  1452.     mov ah,'X'        ; If illegal, replace with "X"
  1453.     mov flags.nmoflg,1
  1454.     ret
  1455.  
  1456. ; Print incoming filename(s). [21a]
  1457. PRTFN    PROC
  1458.  
  1459.     call clrfln        ; Position cursor & blank out the line
  1460.  
  1461.     mov di, OFFSET data    ; Where to put the name
  1462.     cmp flags.nmoflg, 0    ; Is filename in packet?
  1463.      je prtfn1        ; no, keep going
  1464.  
  1465.     add di, pack.argbk1    ; bump by length of remote name
  1466.     mov si, OFFSET asmsg    ; something to put after it
  1467.     mov cx, asmln        ; length of it
  1468.     rep movsb        ; add this to the buffer
  1469.  
  1470. prtfn1:    cmp flags.droflg,0    ; Drive specified?
  1471.      je prtfn2        ;  No
  1472.  
  1473.     mov al, BYTE PTR FCB    ; Pick up drive spec from FCB
  1474.     add al, '@'        ; Make it readable
  1475.     stosb            ; Add to buffer
  1476.     mov al, ":"        ; And a colon
  1477.     stosb            ; Add it also
  1478.  
  1479. prtfn2:    mov cx,8        ; At most 8 letters in file name
  1480.     mov si, OFFSET FCB + 1    ; This is the source now
  1481.  
  1482. prtfn3:    lodsb            ; get a letter
  1483.     cmp al,' '        ; Done with name?
  1484.     je prtfn4        ; yes, continue
  1485.  
  1486.     stosb            ; else store
  1487.     loop prtfn3        ; and loop thru rest
  1488.  
  1489. prtfn4: mov si,offset fcb+9    ; Point to file type
  1490.     cmp byte ptr [si],' '    ; is there a type?
  1491.     je prtfn5        ; Nope so we're done
  1492.     mov al,'.'        ; Add the dot
  1493.     stosb
  1494.  
  1495.     mov cx,3        ; At most 3 letters in file type
  1496.     rep movsb        ; copy type (incl trailing spaces)
  1497.  
  1498. prtfn5:    mov ah, WRITEF2        ; Code to write to a file handle
  1499.     mov bx, 1        ; Standard output
  1500.     mov cx, di        ; Copy ending ptr to cx
  1501.     sub cx, OFFSET Data    ; Get length of data
  1502.     mov dx, OFFSET Data    ; Ptr to data
  1503.     int Dos            ; Type it to standard output
  1504.  
  1505. ;tm    mov flags.droflg,0    ; Reset flag once have the full name
  1506.     mov flags.nmoflg,0
  1507.     ret
  1508.  
  1509. PRTFN    ENDP
  1510.  
  1511.  
  1512. ; Print data onto the screen.
  1513. ;
  1514. ; Routine expects: DI = Start of buffer we are to print
  1515. ;           CX = Number of characters to print.     [21c]
  1516.  
  1517. PRTSCR    PROC
  1518.  
  1519.     mov ah, WRITEF2        ; DOS 2.0 file handle write
  1520.     mov bx, 1        ; File handle 1 is standard output
  1521.     mov dx, di        ; Copy buffer ptr to dx
  1522.     int Dos            ; cx was already set up, just type the string
  1523.  
  1524.     ret            ; That's it
  1525.  
  1526. PRTSCR    ENDP
  1527.  
  1528.  
  1529. FIXFCB  PROC
  1530.     push ax            ; Don't forget this.  [22]
  1531.     mov bx,offset fcb+18
  1532.     mov di,offset filsiz
  1533.     mov ax,[bx]
  1534.     mov [di],ax
  1535.     mov bx,offset fcb+16
  1536.     mov ax,[bx]
  1537.     mov 2[di],ax
  1538.     pop ax            ; Get number of chars in last buffer full. [22]
  1539.     sub filsiz+2,ax        ; Get real file size
  1540.     sbb filsiz,0
  1541.     mov bx,offset fcb+18
  1542.     mov di,offset filsiz
  1543.     mov ax,[di]
  1544.     mov [bx],ax
  1545.     mov bx,offset fcb+16
  1546.     mov ax,2[di]
  1547.     mov [bx],ax
  1548.     ret
  1549. FIXFCB    ENDP
  1550.  
  1551. ; Jumping to this location is like retskp.  It assumes the instruction
  1552. ;   after the call is a jmp addr
  1553.  
  1554. RSKP    PROC    NEAR
  1555.     pop bp
  1556.     add bp,3
  1557.     push bp
  1558. ;    ret
  1559. RSKP    ENDP
  1560.  
  1561. ; Jumping here is the same as a ret
  1562.  
  1563. R    PROC    NEAR
  1564.     ret
  1565. R    ENDP
  1566.  
  1567. Code    ENDS
  1568.  
  1569.     END
  1570.